<template>
    <Transition name="zx-zoom-in-top" @before-enter="handleMenuEnter" @after-leave="$emit('dodestroy')">
        <div
            v-show="visible"
            ref="popper"
            :style="{ width: width + 'px' }"
            :class="popperClass"
            class="zx-picker-panel time-select zx-popper"
        >
            <ZxScrollbar noresize wrap-class="zx-picker-panel__content">
                <div
                    v-for="item in items"
                    :key="item.value"
                    class="time-select-item"
                    :class="{ selected: value === item.value, disabled: item.disabled, default: item.value === defaultValue }"
                    :disabled="item.disabled"
                    @click="handleClick(item)"
                >
                    {{ item.value }}
                </div>
            </ZxScrollbar>
        </div>
    </Transition>
</template>

<script type="text/babel">
import ZxScrollbar from '../../../../components/scrollbar';
import scrollIntoView from '@src/utils/scroll-into-view';

const parseTime = function (time) {
    const values = (time || '').split(':');
    if (values.length >= 2) {
        const hours = parseInt(values[0], 10);
        const minutes = parseInt(values[1], 10);

        return {
            hours,
            minutes,
        };
    }
    /* istanbul ignore next */
    return null;
};

const compareTime = function (time1, time2) {
    const value1 = parseTime(time1);
    const value2 = parseTime(time2);

    const minutes1 = value1.minutes + value1.hours * 60;
    const minutes2 = value2.minutes + value2.hours * 60;

    if (minutes1 === minutes2) {
        return 0;
    }

    return minutes1 > minutes2 ? 1 : -1;
};

const formatTime = function (time) {
    return (time.hours < 10 ? '0' + time.hours : time.hours) + ':' + (time.minutes < 10 ? '0' + time.minutes : time.minutes);
};

const nextTime = function (time, step) {
    const timeValue = parseTime(time);
    const stepValue = parseTime(step);

    const next = {
        hours: timeValue.hours,
        minutes: timeValue.minutes,
    };

    next.minutes += stepValue.minutes;
    next.hours += stepValue.hours;

    next.hours += Math.floor(next.minutes / 60);
    next.minutes = next.minutes % 60;

    return formatTime(next);
};

export default {
    components: { ZxScrollbar },

    data() {
        return {
            popperClass: '',
            start: '09:00',
            end: '18:00',
            step: '00:30',
            value: '',
            defaultValue: '',
            visible: false,
            minTime: '',
            maxTime: '',
            width: 0,
        };
    },

    computed: {
        items() {
            const start = this.start;
            const end = this.end;
            const step = this.step;

            const result = [];

            if (start && end && step) {
                let current = start;
                while (compareTime(current, end) <= 0) {
                    result.push({
                        value: current,
                        disabled: compareTime(current, this.minTime || '-1:-1') <= 0 ||
                            compareTime(current, this.maxTime || '100:100') >= 0,
                    });
                    current = nextTime(current, step);
                }
            }

            return result;
        },
    },

    watch: {
        value(val) {
            if (!val) return;
            this.$nextTick(() => this.scrollToOption());
        },
    },

    methods: {
        handleClick(item) {
            if (!item.disabled) {
                this.$emit('pick', item.value);
            }
        },

        handleClear() {
            this.$emit('pick', null);
        },

        scrollToOption(selector = '.selected') {
            const menu = this.$refs.popper.querySelector('.zx-picker-panel__content');
            scrollIntoView(menu, menu.querySelector(selector));
        },

        handleMenuEnter() {
            const selected = this.items.map(item => item.value).indexOf(this.value) !== -1;
            const hasDefault = this.items.map(item => item.value).indexOf(this.defaultValue) !== -1;
            const option = (selected && '.selected') || (hasDefault && '.default') || '.time-select-item:not(.disabled)';
            this.$nextTick(() => this.scrollToOption(option));
        },

        scrollDown(step) {
            const items = this.items;
            const length = items.length;
            let total = items.length;
            let index = items.map(item => item.value).indexOf(this.value);
            while (total--) {
                index = (index + step + length) % length;
                if (!items[index].disabled) {
                    this.$emit('pick', items[index].value, true);
                    return;
                }
            }
        },

        isValidValue(date) {
            return this.items.filter(item => !item.disabled).map(item => item.value).indexOf(date) !== -1;
        },

        handleKeydown(event) {
            const keyCode = event.keyCode;
            if (keyCode === 38 || keyCode === 40) {
                const mapping = { 40: 1, 38: -1 };
                const offset = mapping[keyCode.toString()];
                this.scrollDown(offset);
                event.stopPropagation();
                return;
            }
        },
    },
};
</script>
